/*******************************************************************************
 * Copyright (c) 2009 Kevin Bierhoff and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     Kevin Bierhoff - initial API and implementation
 *******************************************************************************/
package com.googlecode.twelfdevtools.twelfast;

import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.Region;

import com.googlecode.twelfdevtools.model.IElfFile;
import com.googlecode.twelfdevtools.model.ITwelfModelElement;
import com.googlecode.twelfdevtools.model.ITwelfNamedElement;

public class VariableBinding implements ITwelfBinding {
	
	private final String id;
	private final String def;
	private final ITwelfNamedElement parent;
	/** uniquely identifies this binding, should never be null */
	private final ITwelfTerm binder;
	/** populated by {@link Sync}, so may be <code>null</code> */
	private SourceLocation defLoc;
	
	public VariableBinding(ITwelfTerm binder, String id, String def, ITwelfNamedElement parent) {
		this.binder = binder;
		this.id = id;
		this.def = def;
		this.parent = parent;
	}

	public String getDefinition() {
		return def;
	}
	
	void setDefinitionRangeIfNotDefined(AbstractIdentifier sourceOcc) {
		if(defLoc != null /*&& (sourceOcc.getStartRow() > defLoc.getStartRow() ||
				(sourceOcc.getStartRow() == defLoc.getStartRow() && sourceOcc.getStartColumn() >= defLoc.getStartColumn()))*/)
			// use the first occurrence
			return;
		// hacky but there's no need to copy the location information currently
		// since SourceLocation is a superclass of AbstractIdentifier
		defLoc = sourceOcc;
	}

	public ITwelfNamedElement getModelElement() {
		return new ITwelfNamedElement() {

			public String getDeclaration() {
				return def;
			}

			public String getId() {
				return id;
			}

			public ITwelfModelElement getParent() {
				return parent;
			}
			
			public IElfFile getFile() {
				return parent.getFile();
			}
			
			public IRegion getIdentifierRange(IDocument doc) throws BadLocationException {
				// parser rows and columns are 1-based
				int start = doc.getLineOffset(defLoc.getStartRow()-1) + defLoc.getStartColumn()-1;
				int end = doc.getLineOffset(defLoc.getEndRow()-1) + defLoc.getEndColumn()-1;
				return new Region(start, end - start);
			}
//
//			public int getEndColumn() {
//				return defLoc.getEndColumn();
//			}
//
//			public int getEndRow() {
//				return defLoc.getEndRow();
//			}
//
//			public int getStartColumn() {
//				return defLoc.getStartColumn();
//			}
//
//			public int getStartRow() {
//				return defLoc.getStartRow();
//			}
		};
	}
	
	@Override
	public String toString() {
		return def;
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		// use unique hash code if binder is null
		result = prime * result + ((binder == null) ? super.hashCode() : binder.hashCode());
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		VariableBinding other = (VariableBinding) obj;
		if (binder == null) {
			if (other.binder != null)
				return false;
		} else if (!binder.equals(other.binder))
			return false;
		// do *not* treat two objects with null bindings as equal
		return false;
	}

}
